﻿using ChronoScript_Compiler.Language;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Viper.Opcodes;

namespace ChronoScript_Compiler.CodeGen
{
    public partial class CodeGen
    {
        public void GetStringValue(LanguageDefinition.SyntaxNode sn)
        {
            if (sn is LanguageDefinition.StringLiteral)
            {
                Assembler.Emit(new push_ptr(Symbols.CreateTempString(((LanguageDefinition.StringLiteral)sn).value)));
            }
            else if (sn is LanguageDefinition.FunctionCall)
            {
                LanguageDefinition.FunctionCall fc = sn as LanguageDefinition.FunctionCall;
                if (GetReturnType(fc) != "string")
                    Errors.Add("Method " + fc.Target + " does not return type string!");
                else
                    Call(fc);
            }
            else if (sn is LanguageDefinition.Expression)
            {
                ParseStringExpression(sn as LanguageDefinition.Expression);
            }
            else if (sn is LanguageDefinition.SymbolRef)
            {
                LanguageDefinition.SymbolRef Ref = sn as LanguageDefinition.SymbolRef;
                if (Symbols[Ref.Value] != "")
                {
                    if (Symbols.getType(Ref.Value) != VType.String)
                        Errors.Add(Ref.Value + " can not be converted to string!");
                    else
                    {
                        Assembler.Emit(new push_ptr(Symbols[Ref.Value]));
                        Assembler.Emit(new dload());
                    }

                }
                else
                    Errors.Add(Ref.Value + " does not exist!");
            }
        }

        public void ParseStringExpression(LanguageDefinition.Expression exp)
        {
            foreach (LanguageDefinition.SyntaxNode sn in exp.Items)
            {
                if (sn is LanguageDefinition.Operator)
                {
                    LanguageDefinition.Operator op = sn as LanguageDefinition.Operator;
                    GetStringValue(op.Op1);
                    GetStringValue(op.Op2);
                    if (sn is LanguageDefinition.Plus)
                        Assembler.Emit(new sysf(3));
                    else
                    {
                        Errors.Add("Operator '" + op.theOperator + "' can not be applied between string!");
                    }
                }
                else
                {
                    GetStringValue(sn);
                }
            }
        }
    }
}
